package com.trailwalker.mediaplayer.activity;

import com.trailwalker.JavaUtils.log.LogUtils;
import com.trailwalker.JavaUtils.string.StringUtils;
import com.trailwalker.javafx.core.activity.Activity;
import com.trailwalker.javafx.utils.image.ImageUtils;
import com.trailwalker.javafx.utils.resource.ResourceUtils;
import com.trailwalker.javafx.utils.stage.StageUtils;
import com.trailwalker.javafx.utils.storage.PreferencesManager;
import com.trailwalker.javafx.utils.style.AdaptUtils;
import com.trailwalker.javafx.utils.style.StyleUtils;
import com.trailwalker.javafx.utils.system.ApplicationUtils;
import com.trailwalker.mediaplayer.MediaPlayerApplication;
import com.trailwalker.mediaplayer.customView.MediaBar;
import com.trailwalker.mediaplayer.service.Player;
import com.trailwalker.mediaplayer.service.entity.MediaInfo;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.util.Callback;

import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * @author Trailwalker
 * @create 2021-09-05 16:08
 */
public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private Player player;
    private ArrayList<MediaInfo> mediaArrayList;
    private ListView<MediaInfo> lvMedia;
    private ObservableList<MediaInfo> sourceMediaList;
    private ObservableList<MediaInfo> filterMediaList;

    private Activity mActivity;
    private AdaptUtils mAdaptUtils;
    private ImageView mIvClose;
    private ImageView mIvIconified;
    private ImageView mIvTheme;
    private TextField mTfSearch;
    private Button mBtnAddFile;
    private Button mBtnAddFileDirectory;
    private Button mBtnPlayAll;

    @Override
    public void onCreate() {
        super.onCreate();
        initLoad();
        initView();
        initData();
        initListener();
    }

    private void initListener() {
        if (mIvClose != null) {
            mIvClose.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    if (event.getButton().equals(MouseButton.PRIMARY)) {
                        ApplicationUtils.exit();
                    }
                }
            });
        }

        if (mIvIconified != null) {
            mIvIconified.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    if (event.getButton().equals(MouseButton.PRIMARY)) {
                        StageUtils.setIconified(getApplication().getStage());
                    }
                }
            });
        }

        if (mIvTheme != null) {
            mIvTheme.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    if (event.getButton().equals(MouseButton.PRIMARY)) {
                        ContextMenu contextMenu = new ContextMenu();
                        contextMenu.getStyleClass().add("context_menu_background");
                        CustomMenuItem lightMenuItem = new CustomMenuItem();

                        HBox hbItemLight = new HBox();
                        lightMenuItem.setContent(hbItemLight);
                        mAdaptUtils.setScaleWidth(hbItemLight, 100);
                        hbItemLight.setSpacing(mAdaptUtils.getScale(15));
                        hbItemLight.setAlignment(Pos.CENTER_LEFT);
                        hbItemLight.setOnMouseClicked(new EventHandler<MouseEvent>() {
                            @Override
                            public void handle(MouseEvent event) {
                                if (event.getButton().equals(MouseButton.PRIMARY)) {
                                    ObservableList<String> stylesheets = getApplication().getScene().getStylesheets();
                                    stylesheets.clear();
                                    stylesheets.add(ResourceUtils.getCss(MainActivity.this,"lightTheme.css"));
                                    PreferencesManager.getInstance().putInt("theme", 0);
                                }
                            }
                        });

                        Label ivLight = new Label();
                        hbItemLight.getChildren().add(ivLight);
                        mAdaptUtils.setScaleSize(ivLight, 30);
                        StyleUtils.setBackgroundColor(ivLight, "#ffffff");

                        Label lblLight = new Label();
                        hbItemLight.getChildren().add(lblLight);
                        lblLight.getStyleClass().add("lbl_text_color");
                        mAdaptUtils.setScaleTextSize(lblLight, 25);
                        lblLight.setText("明亮");

                        CustomMenuItem darkMenuItem = new CustomMenuItem();

                        HBox hbItemDark = new HBox();
                        darkMenuItem.setContent(hbItemDark);
                        hbItemDark.setAlignment(Pos.CENTER_LEFT);
                        mAdaptUtils.setScaleWidth(hbItemDark, 100);
                        hbItemDark.setSpacing(mAdaptUtils.getScale(15));
                        hbItemDark.setOnMouseClicked(new EventHandler<MouseEvent>() {
                            @Override
                            public void handle(MouseEvent event) {
                                if (event.getButton().equals(MouseButton.PRIMARY)) {
                                    ObservableList<String> stylesheets = getApplication().getScene().getStylesheets();
                                    stylesheets.clear();
                                    stylesheets.add(ResourceUtils.getCss(MainActivity.this,"darkTheme.css"));
                                    PreferencesManager.getInstance().putInt("theme", 1);
                                }
                            }
                        });

                        Label ivDark = new Label();
                        hbItemDark.getChildren().add(ivDark);
                        mAdaptUtils.setScaleSize(ivDark, 30);
                        StyleUtils.setBackgroundColor(ivDark, "#000000");

                        Label lblDark = new Label();
                        hbItemDark.getChildren().add(lblDark);
                        lblDark.getStyleClass().add("lbl_text_color");
                        mAdaptUtils.setScaleTextSize(lblDark, 25);
                        lblDark.setText("黑暗");

                        contextMenu.getItems().addAll(lightMenuItem, darkMenuItem);
                        contextMenu.show(mIvTheme, Side.BOTTOM, 0, 0);
                    }
                }
            });
        }

        if (player != null) {
            player.setOnPlaying(new Runnable() {
                @Override
                public void run() {
                    if (lvMedia != null) {
                        lvMedia.refresh();
                    }
                }
            });
        }

        if (mTfSearch != null) {
            mTfSearch.textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    filterMediaList = sourceMediaList.filtered(new Predicate<MediaInfo>() {
                        @Override
                        public boolean test(MediaInfo mediaInfo) {
                            if (mediaInfo.getName().contains(newValue)) {
                                return true;
                            } else {
                                return false;
                            }
                        }
                    });
                    lvMedia.setItems(filterMediaList);
                }
            });
        }

        if (mBtnAddFile != null) {
            mBtnAddFile.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    FileChooser fileChooser = new FileChooser();
                    fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("音频文件", "*.mp3"));
                    List<File> fileList = fileChooser.showOpenMultipleDialog(getApplication().getStage());
                    addFileList(fileList);
                }
            });
        }

        if (mBtnAddFileDirectory != null) {
            mBtnAddFileDirectory.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    DirectoryChooser directoryChooser = new DirectoryChooser();
                    File file = directoryChooser.showDialog(getApplication().getStage());
                    if (file != null && file.exists()) {
                        File[] files = file.listFiles(new FileFilter() {
                            @Override
                            public boolean accept(File pathname) {
                                if (pathname.getName().endsWith(".mp3")) {
                                    return true;
                                } else {
                                    return false;
                                }
                            }
                        });
                        if (files != null && file.length() > 0) {
                            List<File> fileList = new ArrayList<>(Arrays.asList(files));
                            addFileList(fileList);
                        }
                    }
                }
            });
        }

        if (mBtnPlayAll != null) {
            mBtnPlayAll.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    int currentIndex = mediaArrayList.size() - 1;
                    if (filterMediaList == null || filterMediaList.size() == 0) {
                        mediaArrayList.addAll(sourceMediaList);
                    } else {
                        mediaArrayList.addAll(filterMediaList);
                    }
                    if (mediaArrayList.size() > currentIndex + 1) {
                        player.play(currentIndex + 1);
                    }
                }
            });
        }
    }

    private void addFileList(List<File> fileList) {
        if (fileList != null) {
            for (int i = 0; i < fileList.size(); i++) {
                File file = fileList.get(i);
                if (!isMediaExist(file)) {
                    LogUtils.log(TAG, "发现文件 >> " + file.getName());
                    String url = null;
                    try {
                        url = file.toURI().toURL().toExternalForm();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                    if (StringUtils.isValid(url)) {
                        LogUtils.log(TAG, "文件 " + file.getName() + " 存在");
                        final String finalUrl = url;
                        Media media = new Media(url);
                        MediaPlayer mediaPlayer = new MediaPlayer(media);
                        mediaPlayer.setOnReady(new Runnable() {
                            @Override
                            public void run() {
                                LogUtils.log(TAG, "加载文件 " + file.getName() + " 成功");
                                MediaInfo mediaInfo = new MediaInfo();
                                mediaInfo.setName(file.getName());
                                mediaInfo.setUrl(finalUrl);
                                mediaInfo.setTotalTime(media.getDuration().toSeconds());
                                sourceMediaList.add(mediaInfo);
                                ((MediaPlayerApplication) getApplication()).getMediaPlayerDataService().insertMediaInfo(mediaInfo);
                            }
                        });
                    }
                }
            }
        }
    }

    public boolean isMediaExist(File file) {
        for (int i = 0; i < sourceMediaList.size(); i++) {
            MediaInfo mediaInfo = sourceMediaList.get(i);
            if (mediaInfo.getName().equals(file.getName())) {
                return true;
            }
        }
        return false;
    }

    private void initData() {

    }

    private void initLoad() {
        mActivity = this;
        mAdaptUtils = AdaptUtils.getInstance();

        mediaArrayList = new ArrayList<>();
        mediaArrayList.add(new MediaInfo("civic.mp3", ResourceUtils.getMusic(this, "civic.mp3")));
        mediaArrayList.add(new MediaInfo("MapleStory.mp3", ResourceUtils.getMusic(this, "MapleStory.mp3")));
        player = new Player.Builder(mediaArrayList).build();
    }

    private void initView() {
        AnchorPane apRoot = new AnchorPane();
        setContentView(apRoot);

        BorderPane bpRoot = new BorderPane();
        apRoot.getChildren().add(bpRoot);
        mAdaptUtils.setMatchParentAnchorPane(bpRoot);
        bpRoot.getStyleClass().add("root_background");

        AnchorPane apTitle = new AnchorPane();
        bpRoot.setTop(apTitle);
        setTitleView(getApplication().getStage(), apTitle);
        mAdaptUtils.setScaleHeight(apTitle, 40);
        apTitle.getStyleClass().add("title_background");

        HBox hbTitle = new HBox();
        apTitle.getChildren().add(hbTitle);
        mAdaptUtils.setMatchParentAnchorPane(hbTitle);
        hbTitle.setAlignment(Pos.CENTER);
        mAdaptUtils.setScalePaddingLeftAndRight(hbTitle, 10);

        ImageView ivIcon = new ImageView();
        hbTitle.getChildren().add(ivIcon);
        ivIcon.setFitWidth(mAdaptUtils.getScale(25));
        ivIcon.setFitHeight(mAdaptUtils.getScale(25));
        ivIcon.setImage(new Image(ResourceUtils.getImage(this,"avatar.jpg")));

        Label lblTitle = new Label();
        hbTitle.getChildren().add(lblTitle);
        lblTitle.setText("网抑云音乐");
        mAdaptUtils.setScaleTextSize(lblTitle, 20);
        HBox.setMargin(lblTitle, new Insets(0, 0, 0, mAdaptUtils.getScale(15)));
        lblTitle.getStyleClass().add("lbl_title");

        HBox hbSearchContainer = new HBox();
        hbTitle.getChildren().add(hbSearchContainer);
        hbSearchContainer.getStyleClass().add("title_search_background");
        HBox.setMargin(hbSearchContainer, new Insets(0, 0, 0, mAdaptUtils.getScale(15)));
        mAdaptUtils.setBackgroundRadius(hbSearchContainer, 13);
        hbSearchContainer.setAlignment(Pos.CENTER);
        hbSearchContainer.setPrefHeight(mAdaptUtils.getScale(25));
        hbSearchContainer.setMaxHeight(mAdaptUtils.getScale(25));
        mAdaptUtils.setScaleWidth(hbSearchContainer, 150);

        mTfSearch = new TextField();
        hbSearchContainer.getChildren().add(mTfSearch);
        HBox.setHgrow(mTfSearch, Priority.ALWAYS);
        mTfSearch.setBackground(null);

        Region rEmpty = new Region();
        hbTitle.getChildren().add(rEmpty);
        HBox.setHgrow(rEmpty, Priority.ALWAYS);

        mIvTheme = ImageUtils.getImageView(this,20, "theme_normal.png", "theme_press.png");
        hbTitle.getChildren().add(mIvTheme);
        HBox.setMargin(mIvTheme, new Insets(0, mAdaptUtils.getScale(30), 0, 0));

        mIvIconified = ImageUtils.getImageView(this,20, "iconified_normal.png", "iconified_press.png");
        hbTitle.getChildren().add(mIvIconified);
        HBox.setMargin(mIvIconified, new Insets(0, mAdaptUtils.getScale(15), 0, 0));

        mIvClose = ImageUtils.getImageView(this,20, "close_normal.png", "close_press.png");
        hbTitle.getChildren().add(mIvClose);

        AnchorPane apBottom = new AnchorPane();
        bpRoot.setBottom(apBottom);

        MediaBar mediaBar = new MediaBar.Builder(player).build();
        apBottom.getChildren().add(mediaBar);
        mAdaptUtils.setMatchParentAnchorPane(mediaBar);

        sourceMediaList = FXCollections.observableArrayList();
        sourceMediaList.addAll(((MediaPlayerApplication) getApplication()).getMediaPlayerDataService().getMediaInfoList());

        AnchorPane apCenter = new AnchorPane();
        bpRoot.setCenter(apCenter);

        BorderPane bpLvMediaContainer = new BorderPane();
        apCenter.getChildren().add(bpLvMediaContainer);
        mAdaptUtils.setMatchParentAnchorPane(bpLvMediaContainer);

        AnchorPane apLvMediaTop = new AnchorPane();
        bpLvMediaContainer.setTop(apLvMediaTop);
        apLvMediaTop.getStyleClass().add("add_file_container");
        mAdaptUtils.setScaleHeight(apLvMediaTop, 40);

        HBox hbAddFileContainer = new HBox();
        apLvMediaTop.getChildren().add(hbAddFileContainer);
        hbAddFileContainer.setAlignment(Pos.CENTER);
        mAdaptUtils.setMatchParentAnchorPane(hbAddFileContainer);

        mBtnPlayAll = new Button();
        hbAddFileContainer.getChildren().add(mBtnPlayAll);
        mBtnPlayAll.getStyleClass().add("btn_accent");
        mAdaptUtils.setScaleSize(mBtnPlayAll, 100, 25);
        mAdaptUtils.setScalePadding(mBtnPlayAll, 0);
        mAdaptUtils.setBackgroundRadius(mBtnPlayAll, 5);
        HBox.setMargin(mBtnPlayAll, mAdaptUtils.getMarginLeft(15, HBox.getMargin(mBtnPlayAll)));
        mBtnPlayAll.setText("播放全部");

        Region rAddFileEmpty = new Region();
        hbAddFileContainer.getChildren().add(rAddFileEmpty);
        HBox.setHgrow(rAddFileEmpty, Priority.ALWAYS);

        mBtnAddFile = new Button();
        hbAddFileContainer.getChildren().add(mBtnAddFile);
        mBtnAddFile.getStyleClass().add("btn_accent");
        mAdaptUtils.setScaleSize(mBtnAddFile, 70, 25);
        mAdaptUtils.setScalePadding(mBtnAddFile, 0);
        mAdaptUtils.setBackgroundRadius(mBtnAddFile, 5);
        HBox.setMargin(mBtnAddFile, mAdaptUtils.getMarginRight(15, HBox.getMargin(mBtnAddFile)));
        mBtnAddFile.setText("添加文件");

        mBtnAddFileDirectory = new Button();
        hbAddFileContainer.getChildren().add(mBtnAddFileDirectory);
        mBtnAddFileDirectory.getStyleClass().add("btn_accent");
        mAdaptUtils.setScaleSize(mBtnAddFileDirectory, 70, 25);
        mAdaptUtils.setScalePadding(mBtnAddFileDirectory, 0);
        mAdaptUtils.setBackgroundRadius(mBtnAddFileDirectory, 5);
        HBox.setMargin(mBtnAddFileDirectory, mAdaptUtils.getMarginRight(15, HBox.getMargin(mBtnAddFileDirectory)));
        mBtnAddFileDirectory.setText("添加目录");

        AnchorPane apLvMediaCenter = new AnchorPane();
        bpLvMediaContainer.setCenter(apLvMediaCenter);

        lvMedia = new ListView<>(sourceMediaList);
        apLvMediaCenter.getChildren().add(lvMedia);
        mAdaptUtils.setMatchParentAnchorPane(lvMedia);
        lvMedia.setId("lvMedia");
        lvMedia.setPadding(Insets.EMPTY);
        lvMedia.setCellFactory(new Callback<ListView<MediaInfo>, ListCell<MediaInfo>>() {
            @Override
            public ListCell<MediaInfo> call(ListView<MediaInfo> param) {

                ListCell<MediaInfo> listCell = new ListCell<MediaInfo>() {
                    @Override
                    protected void updateItem(MediaInfo item, boolean empty) {
                        super.updateItem(item, empty);

                        HBox hbItemContainer = new HBox();
                        mAdaptUtils.setScaleHeight(hbItemContainer, 30);
                        hbItemContainer.setAlignment(Pos.CENTER);
                        hbItemContainer.setSpacing(mAdaptUtils.getScale(30));

                        if (!empty) {
                            HBox hbIndexContainer = new HBox();
                            hbItemContainer.getChildren().add(hbIndexContainer);
                            mAdaptUtils.setScaleWidth(hbIndexContainer, 40);
                            hbIndexContainer.setAlignment(Pos.CENTER);

                            if (item.getName().equals(player.getCurrentMediaInfo().getName())) {
                                ImageView ivPlaying = ImageUtils.getImageView(this,15, "playing.png", "");
                                hbIndexContainer.getChildren().add(ivPlaying);
                            } else {
                                int index = getIndex();
                                Label lblIndex = new Label();
                                hbIndexContainer.getChildren().addAll(lblIndex);
                                lblIndex.setText(String.valueOf(index));
                                lblIndex.getStyleClass().add("lbl_text_color");
                                lblIndex.setAlignment(Pos.CENTER);
                                mAdaptUtils.setScaleTextSize(lblIndex, 15);
                            }

                            HBox hbLblNameContainer = new HBox();
                            hbItemContainer.getChildren().add(hbLblNameContainer);
                            hbLblNameContainer.setAlignment(Pos.CENTER_LEFT);
                            HBox.setHgrow(hbLblNameContainer, Priority.ALWAYS);

                            Label lblName = new Label();
                            hbLblNameContainer.getChildren().add(lblName);
                            lblName.setText(item.getName());
                            lblName.getStyleClass().add("lbl_text_color");
                            mAdaptUtils.setScaleTextSize(lblName, 15);

                            Label lblTotalTime = new Label();
                            hbItemContainer.getChildren().add(lblTotalTime);
                            lblTotalTime.setText(mediaBar.getShowTime((int) item.getTotalTime()));
                            lblTotalTime.getStyleClass().add("lbl_text_color");
                            lblTotalTime.setAlignment(Pos.CENTER);
                            mAdaptUtils.setScaleTextSize(lblTotalTime, 15);
                            mAdaptUtils.setScaleWidth(lblTotalTime, 80);
                        }
                        this.setGraphic(hbItemContainer);
                    }
                };
                listCell.setPadding(Insets.EMPTY);
                listCell.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent event) {
                        if (event.getClickCount() == 2) {
                            MediaInfo item = listCell.getItem();
                            if (item != null) {
                                LogUtils.log(TAG, item.getName());
                                if (item.getUrl() != null) {
                                    mediaArrayList.add(item);
                                    player.play(mediaArrayList.size() - 1);
                                }
                            }
                        }
                    }
                });
                return listCell;
            }
        });
    }
}
